package com.shoparc.geo;

import java.util.ArrayList;
import java.util.Iterator;

import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;

import processing.core.PApplet;

public class Polyline extends Element {

	boolean closed = false;

	public Polyline(ArrayList<Vector3D> vertices) {
		super(vertices);
	}

	public void render(PApplet parent) {
		parent.beginShape();

		for (Vector3D v : vertices) {
			parent.vertex((float) v.getX(), (float) v.getY(), (float) v.getZ());
		}

		if (closed) {
			Vector3D v = vertices.get(0);
			parent.vertex((float) v.getX(), (float) v.getY(), (float) v.getZ());
		}

		parent.endShape();
	}

	ArrayList<Polyline> explode() {
		return null;

	}

	public ArrayList<Vector3D> divideByLengthLazy(double l) {
		ArrayList<Vector3D> points = new ArrayList<Vector3D>();

		Iterator<Vector3D> iterator = vertices.iterator();
		Vector3D currentPt = iterator.next();
		points.add(new Vector3D(currentPt.getX(), currentPt.getY(), currentPt
				.getZ()));

		while (iterator.hasNext()) {
			Vector3D nextPt = iterator.next();
			double currentDist = currentPt.distance(nextPt);
			int count = (int) Math.floor((currentDist / l));
			double l2 = currentDist/count;

			Vector3D gradient = new Vector3D(nextPt.getX(), nextPt.getY(),
					nextPt.getZ());
			gradient = gradient.subtract(currentPt);

			for (int i = 0; i < count-1; i++) {

				gradient = gradient.normalize();

				gradient = gradient.scalarMultiply(l2 * (i + 1));
				Vector3D dividePt = new Vector3D(currentPt.getX(),
						currentPt.getY(), currentPt.getZ());
				dividePt = dividePt.add(gradient);
				points.add(dividePt);
			}

			currentPt = nextPt;
			points.add(new Vector3D(currentPt.getX(), currentPt.getY(),
					currentPt.getZ()));
		}

		return points;
	}
	
	public ArrayList<Vector3D> divideByLengthConstant(double l) {
		ArrayList<Vector3D> points = new ArrayList<Vector3D>();

		Iterator<Vector3D> iterator = vertices.iterator();
		Vector3D currentPt = iterator.next();
		points.add(new Vector3D(currentPt.getX(), currentPt.getY(), currentPt
				.getZ()));

		while (iterator.hasNext()) {
			Vector3D nextPt = iterator.next();
			double currentDist = currentPt.distance(nextPt);
			int count = (int) Math.floor((currentDist / l));
			

			Vector3D gradient = new Vector3D(nextPt.getX(), nextPt.getY(),
					nextPt.getZ());
			gradient = gradient.subtract(currentPt);

			for (int i = 0; i < count; i++) {

				gradient = gradient.normalize();

				gradient = gradient.scalarMultiply(l * (i + 1));
				Vector3D dividePt = new Vector3D(currentPt.getX(),
						currentPt.getY(), currentPt.getZ());
				dividePt = dividePt.add(gradient);
				points.add(dividePt);
			}

			currentPt = nextPt;
			points.add(new Vector3D(currentPt.getX(), currentPt.getY(),
					currentPt.getZ()));
		}

		return points;
	}

	public ArrayList<Vector3D> divideByLengthLazy(double l, double offset) {
		ArrayList<Vector3D> points = new ArrayList<Vector3D>();

		Iterator<Vector3D> iterator = vertices.iterator();
		Vector3D currentPt = iterator.next();
		points.add(new Vector3D(currentPt.getX(), currentPt.getY(), currentPt
				.getZ()));

		while (iterator.hasNext()) {
			Vector3D nextPt = iterator.next();
			double currentDist = currentPt.distance(nextPt);
			int count = (int) Math.floor((currentDist / l));
			double l2 = currentDist/count;

			Vector3D gradient = new Vector3D(nextPt.getX(), nextPt.getY(),
					nextPt.getZ());
			gradient = gradient.subtract(currentPt);

			for (int i = 0; i < count; i++) {

				gradient = gradient.normalize();

				gradient = gradient.scalarMultiply(l2 * (i + 1-offset));
				Vector3D dividePt = new Vector3D(currentPt.getX(),
						currentPt.getY(), currentPt.getZ());
				dividePt = dividePt.add(gradient);
				points.add(dividePt);
			}

			currentPt = nextPt;
			points.add(new Vector3D(currentPt.getX(), currentPt.getY(),
					currentPt.getZ()));
		}

		return points;
	}
	
	public ArrayList<Vector3D> divideByLengthGrowing(double start, double low, double high, double rate) {
		
		double avg = (high+low)/low;
		ArrayList<Vector3D> points = new ArrayList<Vector3D>();

		Iterator<Vector3D> iterator = vertices.iterator();
		Vector3D currentPt = iterator.next();
		points.add(new Vector3D(currentPt.getX(), currentPt.getY(), currentPt
				.getZ()));

		
		while (iterator.hasNext()) {
			
			Vector3D nextPt = iterator.next();
			double maxDist = currentPt.distance(nextPt);
			double currentDist = 0;


			Vector3D gradient = new Vector3D(nextPt.getX(), nextPt.getY(),
					nextPt.getZ());
			gradient = gradient.subtract(currentPt);
			double count = start;
			while(currentDist<maxDist){
				
				gradient = gradient.normalize();
				count+=rate;
				if((count>high)||(count<low)){
					rate = -rate;
				}
		

				if(currentDist>0){
					gradient = gradient.scalarMultiply((currentDist));
				}
				Vector3D dividePt = new Vector3D(currentPt.getX(),
						currentPt.getY(), currentPt.getZ());
				dividePt = dividePt.add(gradient);
				points.add(dividePt);
				//width=width%high;
				currentDist+=(count);
			}

			currentPt = nextPt;
			points.add(new Vector3D(currentPt.getX(), currentPt.getY(),
					currentPt.getZ()));
			
		}

		return points;
	}

	ArrayList<Vector3D> divideByLength(double l) {
		// TODO
		double currentDist = 0;
		ArrayList<Vector3D> points = new ArrayList<Vector3D>();
		Iterator<Vector3D> iterator = vertices.iterator();

		Vector3D startPoint = iterator.next();
		Vector3D cursorPoint = new Vector3D(startPoint.getX(),
				startPoint.getY(), startPoint.getZ());
		Vector3D prevCursorPoint = cursorPoint;

		points.add(prevCursorPoint); // We add the starting point
		Vector3D prevPoint = prevCursorPoint;

		cursorPoint = iterator.next();
		currentDist += cursorPoint.distance(prevCursorPoint);
		if (currentDist >= l) {
			// we need to go back

		}

		return points;
	}

}
